package v1

import (
	"github.com/gin-gonic/gin"
	"strconv"
	"strings"
	"time"
	"web_framework/config"
	"web_framework/model"
	"web_framework/pkg/constvar"
	. "web_framework/pkg/e"
	"web_framework/pkg/errno"
	"web_framework/router/api"
	"web_framework/router/middleware"
	"web_framework/service"
	"web_framework/service/lianle"
	"web_framework/storage"
	"web_framework/websocket/v1/handler"
)

type DeviceAPI struct {
}

func (a DeviceAPI) Name() string {
	return "device API"
}

func (a DeviceAPI) Bind() {
	resourceAPI := config.C.Router.Group("/api/v1/data", middleware.CheckVer(), middleware.TrackLog())
	{
		resourceAPI.GET("router/list", RouterList)
		resourceAPI.GET("router/sn_bind", RouterSnBind)
		resourceAPI.GET("router/wifi_info", WifiInfo)
		resourceAPI.GET("router/set_wifi", SetWifi)
		resourceAPI.GET("router/reset", RouterReset)
		resourceAPI.GET("router/restart", RouterReStart)
		resourceAPI.GET("router/set_password", RouterSetPassword)
		resourceAPI.GET("router/get_limit", RouterSpeedGetLimit)
		resourceAPI.GET("router/set_limit", RouterSpeedSetLimit)
		resourceAPI.GET("router/join_device_info", joinDeviceInfo)
		resourceAPI.GET("set_dpath", RouterSetDPath)

		resourceAPI.GET("st/device_info", STDeviceInfo)
		resourceAPI.GET("st/sn_check", STSnCheck)
		resourceAPI.GET("st/sn_version", STVersion)
		resourceAPI.GET("st/wifi_info", STWifiInfo)
		resourceAPI.GET("st/st_test", STTest)
	}
}

// 4.4.1 获取上次一配置的速度限制
func RouterSpeedGetLimit(c *gin.Context) {

	// 检查参数是否为空
	checkList := []string{"uid", "token", "sn", "sver"}
	err, params := CheckEmptyParams(c, checkList)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	limit, err := service.GetSpeedLimit(params["sn"])
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	errno.OK.Info = "获取即速设置信息成功"
	api.SendResponse(c, errno.OK, limit)
}

// 4.4.2 设置速度限制
func RouterSpeedSetLimit(c *gin.Context) {

	// 检查参数是否为空
	checkList := []string{"uid", "token", "sn", "sver"}
	err, params := CheckEmptyParams(c, checkList)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}
	var upSpeed, downSpeed float64
	if "" == c.Query("upspeed") {
		upSpeed = -1
	} else {
		upSpeed, _ = strconv.ParseFloat(c.Query("upspeed"), 64)
	}
	if "" == c.Query("downspeed") {
		downSpeed = -1
	} else {
		downSpeed, _ = strconv.ParseFloat(c.Query("downspeed"), 64)
	}

	// 推送到 下载模块
	mid, getMidErr := service.GenMid(params["sn"])
	if getMidErr != nil {
		api.SendResponse(c, getMidErr, nil)
		return
	}

	var returnData interface{} = model.ResponseData{
		UpSpeed:   params["upspeed"],
		DownSpeed: params["downspeed"],
	}
	requestMsg := model.Response{
		Mid:   mid,
		Mtype: constvar.MTypeRouterSetSpeedLimitRequest,
		Time:  time.Now().Unix(),
		Data:  &returnData,
	}
	client := []string{params["sn"]}
	errSend := handler.WriteMessage(client, requestMsg)
	if errSend != nil {
		api.SendResponse(c, errno.ErrSetSpeedLimit, nil)
		return
	}
	setLimitSpeedCacheKey := constvar.RouterRedisPrefix + params["sn"] + storage.RedisSetLimitSpeedMidCacheKey + ":" + strconv.Itoa(mid)
	if bool, _ := storage.RedisSet(setLimitSpeedCacheKey, 1, 20); bool == false {
		Log("Info", "更新速度限制缓存标记失败")
	}

	for a := 0; a < constvar.TimeFormatSecond*5; a++ {
		time.Sleep(time.Duration(1) * time.Second)
		fileCache, err := storage.RedisGet(setLimitSpeedCacheKey)
		if err != nil || fileCache == "1" {
			Log("Info", "读取更新速度限制缓存标记失败")
			continue
		}

		// 写入缓存事件
		err = service.SetSpeedLimit(params["sn"], upSpeed, downSpeed)
		if err != nil {
			api.SendResponse(c, err, nil)
			return
		}

		errno.OK.Info = "设置下载上传速度限制成功"
		api.SendResponse(c, errno.OK, nil)
		return
	}

	debugRoundNum := 0
	if config.C.RunMode == "debug" {
		r := RandInt(10, 25)
		if r > 16 {
			debugRoundNum = 1
		}
	}

	if debugRoundNum == 0 {
		api.SendResponse(c, errno.ErrSetSpeedLimitTimeout, nil)
		return
	} else {
		// 写入缓存事件
		err = service.SetSpeedLimit(params["sn"], upSpeed, downSpeed)
		if err != nil {
			api.SendResponse(c, err, nil)
			return
		}
		errno.OK.Info = "设置下载上传速度限制成功"
		api.SendResponse(c, errno.OK, nil)
		return
	}
}

func STTest(c *gin.Context) {

	// 检查参数是否为空
	checkList := []string{"password"}
	err, params := CheckEmptyParams(c, checkList)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	password := params["password"]
	bo := STPasswordCheck(password)
	if ! bo {
		api.SendResponse(c, errno.ErrSTPassword, nil)
		return
	}

	errno.OK.Info = "密码校验成功"
	api.SendResponse(c, errno.OK, password)
}

// 连乐 2.12.1
func STDeviceInfo(c *gin.Context) {

	sn := c.Query("sn")
	mac := c.Query("mac")
	device, err := lianle.STDeviceInfo(sn, mac)
	if err != nil {
		api.SendResponse(c, err, nil)
	} else {
		errno.OK.Info = "获取盛天设备信息成功"
		api.SendResponse(c, errno.OK, device)
	}
}

// 连乐 2.12.2
func STSnCheck(c *gin.Context) {

	sn := c.Query("sn")
	err := lianle.STSnCheck(sn)
	if err != nil {
		api.SendResponse(c, err, nil)
	} else {
		errno.OK.Info = "SN校验成功"
		api.SendResponse(c, errno.OK, nil)
	}
}

// 连乐 2.12.3
func STVersion(c *gin.Context) {

	sn := c.Query("sn")
	data, err := lianle.STVersion(sn)
	if err != nil {
		api.SendResponse(c, err, nil)
	} else {
		errno.OK.Info = "获取设备升级信息成功"
		api.SendResponse(c, errno.OK, data)
	}
}

// 连乐 2.2.1
func STWifiInfo(c *gin.Context) {

	sn := c.Query("sn")
	device, err := lianle.STWifiInfo(sn)
	if err != nil {
		api.SendResponse(c, err, nil)
	} else {
		errno.OK.Info = "获取盛天设备信息成功"
		api.SendResponse(c, errno.OK, device)
	}
}

// 5.6 绑定路由器  SN校验接口
func RouterSnBind(c *gin.Context) {

	// 检查参数是否为空
	checkList := []string{"uid", "token", "bindSn", "sver"}
	err, params := CheckEmptyParams(c, checkList)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	// 校验该 sn 是否已经被绑定过
	uid, _ := strconv.Atoi(params["uid"])
	bo, err := service.CheckDeviceBind(params["bindSn"], uid)
	if err != nil || bo == false {
		api.SendResponse(c, err, nil)
		return
	}

	errno.OK.Info = "绑定成功"
	api.SendResponse(c, errno.OK, nil)
}

// 5.7 获取绑定路由器列表
func RouterList(c *gin.Context) {

	// 检查参数是否为空
	checkList := []string{"uid", "token"}
	err, params := CheckEmptyParams(c, checkList)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	// 获取指定用户的路由器列表信息
	uid, _ := strconv.Atoi(params["uid"])
	bind, _ := service.GetDeviceUserBindCache(uid)

	errno.OK.Info = "获取用户绑定路由器列表成功"
	api.SendResponse(c, errno.OK, bind)
}

// 6.1.1 获取WIFI设置信息
func WifiInfo(c *gin.Context) {

	// 检查参数是否为空
	checkList := []string{"uid", "token", "sn", "sver"}
	err, params := CheckEmptyParams(c, checkList)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	wifiInfo, err := service.GetWifiInfoCache(params["sn"], 0, 0)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	errno.OK.Info = "返回WIFI设置信息"
	api.SendResponse(c, errno.OK, wifiInfo)
}

// 6.1.3 设置WIFI信息
func SetWifi(c *gin.Context) {

	// 检查参数是否为空
	checkList := []string{"uid", "token", "sn", "sver", "ssid_name", "security_mode", "password", "switchWifi2_4", "switchWifi5", "private_hide_name"}
	err, params := CheckEmptyParams(c, checkList)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	bo := STPasswordCheck(params["password"])
	if !bo {
		api.SendResponse(c, errno.ErrSTPassword, nil)
		return
	}

	err = service.WifiSetting(params["sn"], params["ssid_name"], params["password"], params["private_hide_name"], params["security_mode"])
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	switchWifi, _ := strconv.Atoi(params["switchWifi2_4"])
	switchWifi5, _ := strconv.Atoi(params["switchWifi5"])
	_, err = service.GetWifiInfo(params["sn"], switchWifi, switchWifi5)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	errno.OK.Info = "设置WIFI成功"
	api.SendResponse(c, errno.OK, nil)
}

// 6.2.1 恢复出厂设置
func RouterReset(c *gin.Context) {

	// 检查参数是否为空
	checkList := []string{"uid", "token", "sn", "sver"}
	err, params := CheckEmptyParams(c, checkList)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}
	SSidName := "yyets_" + strings.ToLower(GetRandomStr(6))
	err = service.WifiSetting(params["sn"], SSidName, "88888888", "0", "0")
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	errno.OK.Info = "恢复出厂设置成功"
	api.SendResponse(c, errno.OK, nil)
}

// 6.3.1 重启路由器
func RouterReStart(c *gin.Context) {

	// 检查参数是否为空
	checkList := []string{"uid", "token", "sn", "sver"}
	err, params := CheckEmptyParams(c, checkList)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	err = lianle.STWifiReboot(params["sn"])
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	errno.OK.Info = "重启路由器成功"
	api.SendResponse(c, errno.OK, nil)
}

// 6.4.1 重置路由器管理密码
func RouterSetPassword(c *gin.Context) {

	// 检查参数是否为空
	checkList := []string{"uid", "token", "sn", "sver", "password"}
	err, params := CheckEmptyParams(c, checkList)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	bo := STPasswordCheck(params["password"])
	if !bo {
		api.SendResponse(c, errno.ErrSTPassword, nil)
		return
	}

	oldPassword := service.GetRouterPassword(params["sn"])
	err = lianle.STpwdUpdate(params["sn"], oldPassword, params["password"])
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	errno.OK.Info = "重置管理密码成功"
	api.SendResponse(c, errno.OK, nil)
}

// 2.1.1获取详情页面不需要实时更新的设备信息
func joinDeviceInfo(c *gin.Context) {

	var checkJoinDeviceInfoList = []string{"token", "uid", "sn", "sver", "mac"}
	// 检查参数是否为空
	err, params := CheckEmptyParams(c, checkJoinDeviceInfoList)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	deviceUUID := Md5Str(params["sn"] + params["mac"])
	deviceInfoCacheKey := constvar.RouterRedisPrefix + params["sn"] + storage.RedisJoinDeviceInfoKey + ":" + deviceUUID
	res, err := storage.RedisHGetAll(deviceInfoCacheKey)
	if err != nil {
		Log("Info", "获取任务设备详情缓存失败")
	}

	var device model.Device
	if mac ,ok := res["mac"].(string);ok{
		device.Mac = mac
	}
	if ip ,ok := res["ip"].(string);ok{
		device.IP = ip
	}

	errno.OK.Info = "获取数据正常"
	api.SendResponse(c, errno.OK, device)
}

// 8.2 设置下载分区
func RouterSetDPath(c *gin.Context) {

	var checkList = []string{"token", "uid", "sn", "sver", "seq", "uuid", "storage_sn", "path"}
	// 检查参数是否为空
	err, params := CheckEmptyParams(c, checkList)
	if err != nil {
		api.SendResponse(c, err, nil)
		return
	}

	//消息推送
	//mid, _ := service.GenMid(params["sn"])
	//partitionSeq, _ := strconv.Atoi(params["seq"])
	//var requestData = model.Request{
	//	Mid:   mid,
	//	Mtype: constvar.MTypeSetPartitionRequest,
	//	Time:  time.Now().Unix(),
	//	Data: &model.RequestData{
	//		Sn:   params["sn"],
	//		UUID: params["uuid"],
	//		Seq:  partitionSeq,
	//	},
	//}

	// TODO
	//conn := handler.RouterMaps[params["token"]]
	//handler.Route(requestData, conn)

	// 先拿到默认分区数据  准备更新到redis
	var dPath = make(map[string]interface{})
	dPath["sn"] = params["storage_sn"]
	dPath["uuid"] = params["uuid"]
	dPath["seq"] = params["seq"]
	dPath["path"] = params["path"]
	partitionDPathCacheKey := constvar.RouterRedisPrefix + params["sn"] + storage.RedisStoragePartitionDPathKey
	_, err = storage.RedisHSet(partitionDPathCacheKey, dPath, -1)
	if err != nil {
		api.SendResponse(c, errno.ErrSetDefaultPath, nil)
		return
	}

	errno.OK.Info = "设置分区成功"
	api.SendResponse(c, errno.OK, nil)
}
